package projeto.model;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 
 * @author Javatar
 * Classe com função de fazer a leitura dos dados que vão ser passados
 * pelo sistema, com ela definimos alguns objetos essênciais ao funcinamento 
 * do programa como a lista com as opniões dos restaurantes e a lista com os usuários.
 */
public class LeituraDeDados {
	
	public static List<String> opniaoRestaurantes;
	public static String[] tabelaRest;
	
	/**
	 * Método que ler arquivo e cria estabelecimentos
	 * @param fileName O arquivo de estabelecimentos a ser lido
	 * @return Lista com estabelecimentos criados
	 */
	
	public static List<Estabelecimento> lerEstabelecimentos(String fileName){
		
		List<Estabelecimento> estabelecimentos = new ArrayList<Estabelecimento>();
		String[] linhaArquivo = new String[3];
		Estabelecimento estabelecimento;
		String nome;
		String endereco;
		String tipoRefeicao;
		BufferedReader input = null;
		
		try { 
			InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName),"UTF-8");
	        input = new BufferedReader(reader);

			while (input.ready()) { 
				linhaArquivo = input.readLine().split(";");
				
				try{
					nome = linhaArquivo[0];
					endereco = linhaArquivo[1];
					tipoRefeicao = linhaArquivo[2];
					estabelecimento = new Estabelecimento(nome,endereco,tipoRefeicao);
					estabelecimentos.add(estabelecimento);
				
				}catch(Exception e){
					System.err.println("Impossivel adicionar estabeleciomento " + linhaArquivo[0]);
					}
				}
			
			}catch (FileNotFoundException e) {
				System.err.println("Arquivo inexistente.");;
			
			}catch (IOException e2) {
				e2.printStackTrace();
			
			}finally{
				if(input != null)
					try{
						input.close();
					
					}catch(IOException e){
						e.printStackTrace();
					}
			}
			
		return estabelecimentos;
	}
	
	/**
	 * Método que ler arquivo de usuérios e cria usuarios
	 * @param fileName O arquivo de usuarios a ser lido
	 * @return Lista com usuarios criados
	 */
	public static List<Usuario> lerUsuarios(String fileName){
		
		List<Usuario> usuarios = new ArrayList<Usuario>();
		List<String> linhaArquivo;
		String data;
		String nome;
		Usuario user;
		BufferedReader input = null;

		try{
			InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName),"UTF-8");
	        input = new BufferedReader(reader);
			
			tabelaRest = input.readLine().split(";");
			opniaoRestaurantes = Arrays.asList(tabelaRest).subList(2,tabelaRest.length);
			tabelaRest[0] = "Data/Hora";
                        tabelaRest[1] = "Nome";
			while(input.ready()){
				
				List<Integer> opnioes = new ArrayList<Integer>();
				linhaArquivo = Arrays.asList(input.readLine().split(";"));

				data = linhaArquivo.get(0);
				nome = linhaArquivo.get(1);
				linhaArquivo = linhaArquivo.subList(2, linhaArquivo.size());
				
				for(String opiniao: linhaArquivo){
					opnioes.add(Integer.parseInt(opiniao.split(":")[0].trim()));
				}
				
				
				try{
					if(opnioes.size() == opniaoRestaurantes.size()){
						user = new Usuario(data,nome,opnioes);
						usuarios.add(user);											
					}
				}catch(Exception e){
					System.err.println("Erro. usuario " + linhaArquivo.get(1) + " nao foi criado " + e.getMessage());
				}
			}
			
		}catch(FileNotFoundException e){
			System.err.println("Arquivo inexistente.");;
		
		}catch(IOException e2){
			e2.printStackTrace();
		
		}finally{
			try{
				if(input != null)
					input.close();				
			
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		return usuarios;
		
	}
	
	/**
	 * Método que verifica se o arquivo de Estabelecimentos é um arquivo válido
	 * @param arq O Arquivo de Estabelecimentos a ser verificado
	 * @return true se o arquivo válido false se não
	 */
	public static boolean isArquivoEstValid(String arq){
		if (arq == null)
			return false;
		
		final int TAMANHO_LINHA = 3;
		final int TAMANHO_ARQ = 40;
		int cont = 0;
		BufferedReader input = null;
		String[] linha;
		
		try{
			input = new BufferedReader(new FileReader(arq));
			
			while(input.ready()){
				linha = input.readLine().split(";");
				if(linha.length != TAMANHO_LINHA){
					return false;					
				}
				
				if(!(linha[0] instanceof String) || !(linha [1] instanceof String) || !(linha [2] instanceof String)){
					return false;
				}
				cont++;
			}
		if(cont != TAMANHO_ARQ){
			return false;
			
		}
			
		}catch(FileNotFoundException e){
			return false;
		
		}catch(IOException e2){
			return false;
		
		}finally{
			if(input != null){
				try{
					input.close();
				
				}catch(IOException e){
				}
			}
		}
		return true;
	}
	
	/**
	 * Método que verifica se o arquivo de Usuarios é válido
	 * @param arq O arquivo de Usuários a ser verificado
	 * @return true se o arquivo é válido false se não
	 */
	public static boolean isArquivoUserValid(String arq){
		
		if (arq == null)
			return false;
		
		final int TAMANHO_MINIMO_ARQ = 2;
		final int TAMANHO_LINHA = 41;
		BufferedReader input = null;
		int cont = 0;
		String[] linha;
		
		try{
			input = new BufferedReader(new FileReader(arq));
			
			while(input.ready()){
				linha = input.readLine().split(";");
				if(linha.length != TAMANHO_LINHA){
					return false;					
				}
				cont++;
			}
		if(cont < TAMANHO_MINIMO_ARQ){
			return false;
		}
			
		}catch(FileNotFoundException e){
			return false;
		
		}catch(IOException e2){
			return false;
		
		}finally{
			if(input != null){
				try{
					input.close();
				
				}catch(IOException e){
					e.printStackTrace();
				}
			}
		}
		return true;
	}
	
	/**
	 * Formatação de tabela de usuarios para interface grafica
	 * @param usuarios Lista de usuarios a ser formatada
	 * @return Tabela formatada
	 */
	public static String[][] geraMatrizDados(List<Usuario> usuarios){
		String[][] matrizDados = new String[usuarios.size()][usuarios.get(0).getOpnioes().size() +2];
		for (int i = 0; i < usuarios.size(); i++){
			int cont =0;
			matrizDados[i][cont] = usuarios.get(i).getData();
			cont++;
			matrizDados[i][cont] = usuarios.get(i).getNome();
			cont++;
			for(int j = 0; j < usuarios.get(i).getOpnioes().size(); j++){
				matrizDados[i][cont] = Integer.toString(usuarios.get(i).getOpnioes().get(j));
				cont++;
			}
		}
		return matrizDados;
	}
	
	/**
	 * Método que verifica e conserta a consistencia de tabelas de indices dos estabelecimentos
	 * @param ests Lista de estabelecimentos
	 */
	public static void verificaTabelas(List<Estabelecimento> ests){
		for(int i =0; i < opniaoRestaurantes.size(); i++){
			for(Estabelecimento est: ests){
				if(opniaoRestaurantes.get(i).toLowerCase().equals(est.getNome().toLowerCase()) && !(opniaoRestaurantes.get(i).equals(est.getNome()))){
					opniaoRestaurantes.set(i,est.getNome());
				}
			}
		}
	}
	
	
	/**
	 * Formatação de tabela de estabelecimentos para interface grafica
	 * @param ests Lista de estabelecimentos a ser formatada
	 * @return Tabela formatada
	 */
	public static String[][] geraMatrizDadosEsts(List<Estabelecimento> ests){
		String[][] matrizDados = new String[ests.size()][3];
		for (int i = 0; i < ests.size(); i++){
			matrizDados[i][0] = ests.get(i).getNome();
			matrizDados[i][1]= ests.get(i).getEndereco();
			matrizDados[i][2] = ests.get(i).getTipoDeRefeicao().getTipoRefeicao();
		}
		return matrizDados;
	}
	
	public static String[][] geraMatrizDadosEstsPopu(List<Estabelecimento> ests){
		String[][] matrizDados = new String[ests.size()][4];
		for (int i = 0; i < ests.size(); i++){
			matrizDados[i][0] = ests.get(i).getNome();
			matrizDados[i][1]= ests.get(i).getEndereco();
			matrizDados[i][2] = ests.get(i).getTipoDeRefeicao().getTipoRefeicao();
			matrizDados[i][3]= Integer.toString(ests.get(i).getPopularidade());
		}
		return matrizDados;
	}
}